package com.itlong.cloud.property.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.DTO.property.PropertyUserInfoGetPageDTO;
import com.itlong.cloud.POJO.DTO.property.PropertyUserLoginDTO;
import com.itlong.cloud.POJO.DTO.property.PropertyUserSaveDTO;
import com.itlong.cloud.POJO.PO.PropertyRoleProjectPO;
import com.itlong.cloud.POJO.PO.PropertyUserGroupRolePO;
import com.itlong.cloud.POJO.PO.PropertyUserInfoPO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.property.*;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.DataStatusEnum;
import com.itlong.cloud.enumerate.PropertyPublicRoleEnum;
import com.itlong.cloud.enumerate.SystemTypeEnum;
import com.itlong.cloud.enumerate.ecode.PropertyErrorCodeEnum;
import com.itlong.cloud.property.dao.IPropertyFunctionDao;
import com.itlong.cloud.property.dao.IPropertyUserInfoDao;
import com.itlong.cloud.property.service.IPropertyUserService;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.encrypt.Md5;
import com.itlong.cloud.utils.encrypt.Md5EncryptUtil;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <desc>
 *      物业人员服务层实现类
 * </desc>
 *
 * @createDate 2017/10/13
 */
@Service
@RefreshScope
public class PropertyUserServiceImpl implements IPropertyUserService {

    //物业系统用户信息数据访问接口
    @Autowired
    IPropertyUserInfoDao iPropertyUserInfoDao;

    //Redis工具接口类
    @Autowired
    private RedisService<PropertyUserCacheVO> redisService;

    //Redis工具接口类
    @Autowired
    private RedisService<PropertyLoginErrorCacheVO> loginErrorRedisService;

    @Autowired
    IPropertyFunctionDao iPropertyFunctionDao;

    //RabbitMQ消息队列生产者
    @Autowired
    private MessageSender messageSender;

    @Value("${" + PlatformConstants.PROPERTY_USER_DEFAULT_PASSWORD + "}")
    String  userDefaultPassword;


    String dateFormatStr = "yyyy-MM-dd HH:mm:ss";
    String userIdSeparator = "_";


    /**
     * <desc>
     *      登录验证成功后的处理
     * <desc/>
     * @param   propertyUserInfoPO 登录时查询到的人员对象
     * @return  登录人员的缓存VO
     * @author Biao.R
     * @createDate 2017/10/16
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public PropertyUserLoginCheckVO getLoginDetail(PropertyUserInfoPO propertyUserInfoPO) throws UnsupportedEncodingException {
        //更新redis缓存
        String userId = propertyUserInfoPO.getUserId();
        String cacheKey = String.format("%s%s", RedisConstant.PROPERTY_USER_REDIS_KEY, userId);

        PropertyUserCacheVO propertyUserCacheVO = new PropertyUserCacheVO();
        BeanUtils.copyProperties(propertyUserInfoPO, propertyUserCacheVO);
        propertyUserCacheVO.setLoginDate(new SimpleDateFormat(dateFormatStr).format(new Date()));
        propertyUserCacheVO.setLastOperateTime(propertyUserCacheVO.getLoginDate());
        propertyUserCacheVO.setIsLongTimeNoOperation(false);

        //为了保证异地登录，账号被挤下线的产品效果，现将token设置成与userId相关的动态值
        String token = UserTokenUtil.tokenEncrypt(String.format("%s%s%s",userId,userIdSeparator,LogicIdUtil.bussinessId()),
                PlatformConstants.PROPERTY_USER_TOKEN_KEY, SystemTypeEnum.PROPERTY.getType());

//        String token = UserTokenUtil.tokenEncrypt(userId,PlatformConstants.PROPERTY_USER_TOKEN_KEY, SystemTypeEnum.PROPERTY.getType());
        propertyUserCacheVO.setToken(token);
        redisService.set(cacheKey, RedisConstant.PROPERTY_LOGIN_TIME, propertyUserCacheVO);

        //根据userId 查询登录所需信息（所属项目，以及该项目对应的角色）
        List<PropertyProjectRoleVO> projectRoles  =iPropertyUserInfoDao.getProjectRoleByUserId(userId,null);
        PropertyUserLoginCheckVO checkVO = new PropertyUserLoginCheckVO(userId, propertyUserInfoPO.getUserName(), propertyUserInfoPO.getRealName(),token);
        checkVO.setPropertyName(propertyUserInfoPO.getPropertyName());
        if (projectRoles != null && !projectRoles.isEmpty()) {
            checkVO.setProjectRoleVOList(projectRoles);
            //登录成功后,清除登录错误而产生的缓存数据
            redisService.del(String.format("%s%s", RedisConstant.PROPERTY_LOGIN_ERROR_REDIS_KEY, propertyUserInfoPO.getUserId()));
        }
        // 增加完善信息所需字段
        PropertyUserLoginCheckVO propertyUserLoginCheckVO = iPropertyUserInfoDao.getCompleteInfo(propertyUserInfoPO.getUserId());
        checkVO.setBindPhoneNum(propertyUserLoginCheckVO.getBindPhoneNum());
        checkVO.setUpdatePassword(propertyUserLoginCheckVO.getUpdatePassword());
        checkVO.setCompleteBaseInfo(propertyUserLoginCheckVO.getCompleteBaseInfo());
        checkVO.setPhoneSafety(propertyUserLoginCheckVO.getPhoneSafety());
        checkVO.setAdministratorPhone(propertyUserLoginCheckVO.getAdministratorPhone());
        checkVO.setPropertyPhone(propertyUserLoginCheckVO.getPropertyPhone());
        checkVO.setCountryId(propertyUserLoginCheckVO.getCountryId());
        checkVO.setProvinceId(propertyUserLoginCheckVO.getProvinceId());
        checkVO.setCityId(propertyUserLoginCheckVO.getCityId());
        checkVO.setDistrictId(propertyUserLoginCheckVO.getDistrictId());
        checkVO.setLocation(propertyUserLoginCheckVO.getLocation());
        checkVO.setAddress(propertyUserLoginCheckVO.getAddress());
        checkVO.setPasswordTime(propertyUserLoginCheckVO.getPasswordTime());
        return checkVO;
    }

    /**
     * <desc>
     *      物业注销
     * <desc/>
     * @param   propertyUserLoginDTO    物业登出校验DTO
     * @return  PropertyUserCacheVO 缓存中获取的VO对象
     * @author Biao.R
     * @createDate 2017/10/16
     */
    @Override
    public PropertyUserCacheVO logout(PropertyUserLoginDTO propertyUserLoginDTO) {
        String cacheKey = String.format("%s%s", RedisConstant.PROPERTY_USER_REDIS_KEY,
                propertyUserLoginDTO.getLoginUserId());
        PropertyUserCacheVO propertyUserCacheVO = redisService.getObject(cacheKey, PropertyUserCacheVO.class);
        if (propertyUserCacheVO != null) {
            redisService.del(cacheKey);
        }
        return propertyUserCacheVO;
    }

    /**
     * <desc>
     *      物业用户请求时校验通过token校验用户
     * <desc/>
     * @param   loginUserId  登录用户ID
     * @param   token  登录用户ID
     * @return  PropertyUserLoginCheckVO  物业登录校验DTO
     * @author Biao.R
     * @createDate 2017/10/13
     */
    @Override
    public PropertyUserCacheVO checkCacheUser(String loginUserId, String token) {
        try {
            Date currentTime = new Date();
            String cacheKey = String.format("%s%s", RedisConstant.PROPERTY_USER_REDIS_KEY, loginUserId);
            PropertyUserCacheVO propertyUserCacheVO = redisService.getObject(cacheKey, PropertyUserCacheVO.class);
            if (propertyUserCacheVO != null && token.equals(propertyUserCacheVO.getToken())) {
                //解密token
//                String desToken = UserTokenUtil.tokenDecrypt(propertyUserCacheVO.getToken(), PlatformConstants.PROPERTY_USER_TOKEN_KEY);
                String desToken = UserTokenUtil.tokenDecryptBySSO(propertyUserCacheVO.getToken(), PlatformConstants.PROPERTY_USER_TOKEN_KEY);
                if (StringUtils.isNotEmpty(desToken) && loginUserId.equals(desToken.split(URLEncoder.encode(userIdSeparator, "UTF-8"))[0])) {
                    propertyUserCacheVO.setLastOperateTime(new SimpleDateFormat(dateFormatStr).format(currentTime));
                    redisService.set(cacheKey, RedisConstant.PROPERTY_LOGIN_TIME, propertyUserCacheVO);
                    return propertyUserCacheVO;
                }
            }
            if(propertyUserCacheVO == null){
                PropertyUserCacheVO userCacheVO = new PropertyUserCacheVO();
                userCacheVO.setIsLongTimeNoOperation(true);
                return userCacheVO;
            }
            return null;
        } catch (Exception e) {
            throw new DataAccessException("【物业_checkCacheUser】token校验用户异常", e);
        }
    }


    /**
     * <desc>
     *      修改密码
     * </desc>
     *
     * @param userName 用户名
     * @param password 密码
     * @param newPassword 新密码
     * @return  更新数量
     * @author Biao.R
     * @createDate 2017/10/13
     */
    public Integer updatePassword(String userName, String password, String newPassword) throws Exception {
        Map<String, String> param = new HashMap<>();
        param.put("userName", userName.trim());
        param.put("password", Md5.En(password));
        PropertyUserInfoPO userInfo = iPropertyUserInfoDao.checkUserByUserName(param);
        if (userInfo != null) {
            PropertyUserInfoPO user = new PropertyUserInfoPO();
            user.setUserId(userInfo.getUserId());
            user.setPassword(Md5EncryptUtil.md5(newPassword.trim()));
            return iPropertyUserInfoDao.update(SqlUtil.durableData(user, PlatformConstants.TABLE_UPDATE));
        }
        return null;
    }

    /**
     * <desc>
     *      保存人员
     * </desc>
     * @param  propertyUserSaveDTO 人员实体
     * @return  添加数量
     * @author Biao.R
     * @createDate 2017/09/27
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer save(PropertyUserSaveDTO propertyUserSaveDTO) throws Exception {
        int result;
        Date currentTime = new Date();
        String userId = LogicIdUtil.userBusinessId();
        String userNum = String.format("%08d", Integer.valueOf(iPropertyUserInfoDao.getMaxNum(propertyUserSaveDTO.getProjectId())) + 1);
        PropertyUserInfoPO userInfoPO = new PropertyUserInfoPO();
        BeanUtils.copyProperties(propertyUserSaveDTO, userInfoPO);

        //查询该项目中管理员所归属的物业系统名称
        String propertyName = "";
        String adminUserId = this.getPropertyAdmin(propertyUserSaveDTO.getProjectId());
        if (StringUtils.isNotEmpty(adminUserId)) {
            PropertyUserInfoPO propertyAdmin = iPropertyUserInfoDao.getUserByUserId(adminUserId);
            if (propertyAdmin != null) {
                propertyName = propertyAdmin.getPropertyName();
            }
        }else{
            String adminGroupUserId = this.getPropertyAdminGroup(propertyUserSaveDTO.getProjectId());
            if (StringUtils.isNotEmpty(adminGroupUserId)) {
                PropertyUserInfoPO propertyAdmin = iPropertyUserInfoDao.getUserByUserId(adminGroupUserId);
                if (propertyAdmin != null) {
                    propertyName = propertyAdmin.getPropertyName();
                }
            }
        }
        userInfoPO.setPropertyName(propertyName);
        userInfoPO.setCreateTime(currentTime);
        userInfoPO.setUserId(userId);
        userInfoPO.setUserNum(userNum);
        userInfoPO.setPassword(Md5.En(userDefaultPassword));
        userInfoPO.setStatus(DataStatusEnum.NORMAL.getType());
        userInfoPO.setPasswordTime(new Date());
        result = iPropertyUserInfoDao.save(SqlUtil.durableData(userInfoPO, PlatformConstants.TABLE_SAVE));

        // 保存用户部门角色关系
        List<PropertyUserGroupRolePO> propertyUserGroupRolePOList = JSON.parseArray(propertyUserSaveDTO.getUserGroupRoleJson(), PropertyUserGroupRolePO.class);
        for (PropertyUserGroupRolePO propertyUserGroupRolePO : propertyUserGroupRolePOList) {
            propertyUserGroupRolePO.setUserId(userId);
            propertyUserGroupRolePO.setProjectId(propertyUserSaveDTO.getProjectId());
            propertyUserGroupRolePO.setCreateUserId(propertyUserSaveDTO.getLoginUserId());
            propertyUserGroupRolePO.setOperateUserId(propertyUserSaveDTO.getLoginUserId());
            propertyUserGroupRolePO.setStatus(DataStatusEnum.NORMAL.getType());
            propertyUserGroupRolePO.setCreateTime(currentTime);
            propertyUserGroupRolePO.setUpdateTime(currentTime);
        }
        if (!propertyUserGroupRolePOList.isEmpty()) {
            result += iPropertyUserInfoDao.batchSaveUserGroupRole(propertyUserGroupRolePOList);
        }

        //保存人员角色关系
        List<String> roleIdList = StringHandlerUtil.splitStringList(propertyUserSaveDTO.getRoleId());
        List<PropertyRoleProjectPO> roleProjectPOList = new ArrayList<>();
        for (String roleId : roleIdList) {
            PropertyRoleProjectPO roleProjectPO = new PropertyRoleProjectPO(propertyUserSaveDTO.getProjectId(), roleId, userId);
            roleProjectPO.setStatus(DataStatusEnum.NORMAL.getType());
            roleProjectPO.setCreateTime(currentTime);
            roleProjectPOList.add(roleProjectPO);
        }
        if (!roleProjectPOList.isEmpty()) {
            result += iPropertyUserInfoDao.batchSaveRoleProjectPO(roleProjectPOList);
        }
        return result;
    }

    /**
     * <desc>
     *      更新人员
     * </desc>
     * @param   propertyUserSaveDTO 人员添加DTO
     * @return  更新数量
     * @author Biao.R
     * @createDate 2017/09/27
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer update(PropertyUserSaveDTO propertyUserSaveDTO) throws Exception {
        int result;
        Date currentTime = new Date();
        //查询该用户旧的角色
        Map<String, Object> params = new HashMap<>();
        params.put("projectId", propertyUserSaveDTO.getProjectId());
        params.put("userId", propertyUserSaveDTO.getUserId());
        List<PropertyRoleProjectPO> roleProjectPOList = iPropertyUserInfoDao.getRoleProject(params);

        //更新user信息
        PropertyUserInfoPO userInfoPO = new PropertyUserInfoPO();
        BeanUtils.copyProperties(propertyUserSaveDTO, userInfoPO);

        //查询该项目中管理员所归属的物业系统名称
        String propertyName = "";
        String adminUserId = this.getPropertyAdmin(propertyUserSaveDTO.getProjectId());
        if (StringUtils.isNotEmpty(adminUserId)) {
            PropertyUserInfoPO propertyAdmin = iPropertyUserInfoDao.getUserByUserId(adminUserId);
            if (propertyAdmin != null) {
                propertyName = propertyAdmin.getPropertyName();
            }
        }else{
            String adminGroupUserId = this.getPropertyAdminGroup(propertyUserSaveDTO.getProjectId());
            if (StringUtils.isNotEmpty(adminGroupUserId)) {
                PropertyUserInfoPO propertyAdmin = iPropertyUserInfoDao.getUserByUserId(adminGroupUserId);
                if (propertyAdmin != null) {
                    propertyName = propertyAdmin.getPropertyName();
                }
            }
        }
        userInfoPO.setPropertyName(propertyName);
        userInfoPO.setUpdateTime(currentTime);
        result = iPropertyUserInfoDao.update(SqlUtil.durableData(userInfoPO, PlatformConstants.TABLE_UPDATE));

        // 保存用户部门角色关系
        List<PropertyUserGroupRolePO> propertyUserGroupRolePOList = JSON.parseArray(propertyUserSaveDTO.getUserGroupRoleJson(), PropertyUserGroupRolePO.class);
        for (PropertyUserGroupRolePO propertyUserGroupRolePO : propertyUserGroupRolePOList) {
            propertyUserGroupRolePO.setUserId(propertyUserSaveDTO.getUserId());
            propertyUserGroupRolePO.setProjectId(propertyUserSaveDTO.getProjectId());
            propertyUserGroupRolePO.setCreateUserId(propertyUserSaveDTO.getLoginUserId());
            propertyUserGroupRolePO.setOperateUserId(propertyUserSaveDTO.getLoginUserId());
            propertyUserGroupRolePO.setStatus(DataStatusEnum.NORMAL.getType());
            propertyUserGroupRolePO.setCreateTime(currentTime);
            propertyUserGroupRolePO.setUpdateTime(currentTime);
        }
        if (!propertyUserGroupRolePOList.isEmpty()) {
            String[] userIdArr = {propertyUserSaveDTO.getUserId()};
            iPropertyUserInfoDao.deleteUserGroupRole(userIdArr);
            result += iPropertyUserInfoDao.batchSaveUserGroupRole(propertyUserGroupRolePOList);
        }

        //保存人员角色关系
        List<String> roleIdList = StringHandlerUtil.splitStringList(propertyUserSaveDTO.getRoleId());
        List<PropertyRoleProjectPO> roleProjectPOSaveList = new ArrayList<>();
        for (String roleId : roleIdList) {
            PropertyRoleProjectPO roleProjectPO = new PropertyRoleProjectPO(propertyUserSaveDTO.getProjectId(), roleId, propertyUserSaveDTO.getUserId());
            roleProjectPO.setStatus(DataStatusEnum.NORMAL.getType());
            roleProjectPO.setCreateTime(currentTime);
            roleProjectPOSaveList.add(roleProjectPO);
        }
        if (!roleProjectPOSaveList.isEmpty()) {
            result += iPropertyUserInfoDao.batchSaveRoleProjectPO(roleProjectPOSaveList);
        }

        //删除旧的角色关系
        if (roleProjectPOList != null && !roleProjectPOList.isEmpty()) {
            iPropertyUserInfoDao.deleteUserRolesById(roleProjectPOList);
        }
        return result;
    }

    /**
     * <desc>
     *      根据条件查询人员
     * </desc>
     * @param    params  查询参数
     * @return  List<PropertyUserInfoPO> 人员实体集合
     * @author Biao.R
     * @createDate 2017/10/13
     *
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<PropertyUserInfoPO> getList(Map<String, Object> params) {
        return iPropertyUserInfoDao.getByFields(params);
    }

    /**
     * <desc>
     *      根据条件查询人员是否存在 true为存在 false不存在
     * </desc>
     * @param    params  查询参数
     * @return  是否存在  true为存在 false不存在
     * @author Biao.R
     * @createDate 2017/10/13
     *
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public boolean isPropertyUserExist(Map<String, Object> params) {
        Integer isExist = iPropertyUserInfoDao.isPropertyUserExist(params);
        if (isExist != null && isExist > 0) {
            return true;
        }
        return false;
    }

    /**
     * <desc>
     *      获取分页数据
     * </desc>
     *
     * @param pageDTO   参数DTO
     * @return
     * @author Biao.R
     * @createDate 2017/09/27
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<PropertyUserInfoGetUserPageVO> getPage(PropertyUserInfoGetPageDTO pageDTO)  {
        try {
            //将DTO转换为Map params
            Map<String, Object> params = SqlUtil.convertBeanToMapParams(pageDTO);
            //分页类默认pageSize为20
            Page<PropertyUserInfoGetUserPageVO> page = new Page<>();
            page.getPage().setPageSize(pageDTO.getPageSize());
            page.getPage().setCurrentPage(pageDTO.getCurrentPage());
            params.put("currentPage",page.getPage().getStartSlip());
            params.put("pageSize",page.getPage().getPageSize());
            params.put("projectId",pageDTO.getProjectId());
            //填充返回数据集
            page.setRows(iPropertyUserInfoDao.getPage(params), iPropertyUserInfoDao.getPageCount(params));
            return page;
        } catch (Exception e) {
            throw new DataAccessException("【物业人员服务层_PropertyUserServiceImpl_getPage】处理异常",e);
        }
    }

    /**
     * <desc>
     *      根据id查询人员
     * </desc>
     *
     * @param propertyGroupPO 人员实体
     * @return
     * @author Biao.R
     * @createDate 2017/09/27
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public PropertyUserInfoGetOneVO getOne(PropertyUserInfoPO propertyGroupPO) {
        return iPropertyUserInfoDao.getById(propertyGroupPO.getUserId());
    }

    /**
     * <desc>
     *      删除用户
     * </desc>
     *
     * @param userIds 用户id 多个,号分隔
     * @return sql执行行数
     * @author Biao.R
     * @createDate 2017/09/25
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer delete(String userIds) {
        try {
            String[] userIdArr = StringHandlerUtil.splitString(userIds);
            Integer deleteCount = 0;
            if (userIdArr.length > 0) {
                deleteCount = iPropertyUserInfoDao.delete(userIdArr, new Date());
                deleteCount += iPropertyUserInfoDao.deleteUserProject(userIdArr);
                deleteCount += iPropertyUserInfoDao.deleteUserGroupRole(userIdArr);
                //如果该账号已经登陆，需要清除缓存，使其下线
                List<String> cacheKeyList = new ArrayList<>();
                for (String userId : userIdArr) {
                    cacheKeyList.add(String.format("%s%s", RedisConstant.PROPERTY_USER_REDIS_KEY, userId));
                    //清除物业app登录缓存
                    cacheKeyList.add(String.format("%s%s",RedisConstant.PROPERTY_APP_REDIS_USER_KEY,userId));
                }
                JSONObject datajs = new JSONObject();
                datajs.put("data",cacheKeyList);
                messageSender.send(RabbitMQConstant.RABBITMQ_DELETE_CACHE_QUEUE, JsonUtil.toJSON(datajs), RabbitMQConstant.RABBITMQ_USER_EXCHANGE,
                        RabbitMQConstant.RABBITMQ_DELETE_CACHE_KEY);
            }
            return deleteCount;
        } catch (Exception e) {
            throw new DataAccessException("【物业人员服务层_PropertyUserServiceImpl_delete】删除物业人员异常", e);
        }
    }

    /**
     * <desc>
     *      重置用户密码
     * </desc>
     *
     * @param userIds 用户id数组
     * @return
     * @author Biao.R
     * @createDate 2017/10/12
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer resetPassword(String userIds) {
        return iPropertyUserInfoDao.resetPassword(
                StringHandlerUtil.splitString(userIds),
                Md5EncryptUtil.md5(userDefaultPassword),
                new Date()
        );
    }

    /**
     * <desc>
     *      根据项目ID获取该项目的物业管理员userId
     * <desc/>
     * @param  projectId  待查询的项目ID
     * @return String   物业管理员userId
     * @author Biao.R
     * @createDate 2017/11/9
     */
    @Override
    public String getPropertyAdmin(String projectId) {
        if (StringUtils.isNotEmpty(projectId)) {
            Map<String, Object> params = new HashMap<>();
            params.put("projectId", projectId);
            params.put("roleId", PropertyPublicRoleEnum.ADMIN.getRoleId());
            List<PropertyRoleProjectPO> roleProjectPOList = iPropertyUserInfoDao.getRoleProject(params);
            if (roleProjectPOList != null && !roleProjectPOList.isEmpty()) {
                return roleProjectPOList.get(0).getUserId();
            }
        }
        return null;
    }

    /**
     * <desc>
     *      根据项目ID获取该项目的集团物业管理员userId
     * <desc/>
     * @param  projectId  待查询的项目ID
     * @return String   物业管理员userId
     * @author Juguang.S
     * @createDate 2018/07/30
     */
    public String getPropertyAdminGroup(String projectId) {
        if (StringUtils.isNotEmpty(projectId)) {
            Map<String, Object> params = new HashMap<>();
            params.put("projectId", projectId);
            params.put("roleId", PropertyPublicRoleEnum.GROUP_ADMIN.getRoleId());
            List<PropertyRoleProjectPO> roleProjectPOList = iPropertyUserInfoDao.getRoleProject(params);
            if (roleProjectPOList != null && !roleProjectPOList.isEmpty()) {
                return roleProjectPOList.get(0).getUserId();
            }
        }
        return null;
    }

    /**
     * <desc>
     *      更新property_user_info单表
     * <desc/>
     * @param   userInfoPO   待更新对象
     * @return 更新数量
     * @author Biao.R
     * @createDate 2017/11/13
     */
    @Override
    public Integer updateUser(PropertyUserInfoPO userInfoPO) {
        try {
            if (userInfoPO == null) {
                return null;
            }
            return iPropertyUserInfoDao.update(SqlUtil.durableData(userInfoPO, PlatformConstants.TABLE_UPDATE));
        } catch (Exception e) {
            throw new DataAccessException("【物业人员服务层_PropertyUserServiceImpl_updateUser】处理异常", e);
        }
    }

    /**
     * <desc>
     *      根据项目编号和项目物业管理员密码校验登录用户
     * <desc/>
     * @param  param    校验参数
     * @return  查询到的用户信息
     * @author Biao.R
     * @createDate 2017/12/10
     */
    @Override
    public PropertyUserInfoPO checkUserByProjectId(Map<String, Object> param) {
        if (param == null || param.isEmpty()) {
            return null;
        }
        return iPropertyUserInfoDao.checkUserByProjectId(param);
    }

    /**
     * <desc>
     *      根据物业帐号和密码校验登录用户
     * <desc/>
     * @param  param    校验参数
     * @return  查询到的用户信息
     * @author Biao.R
     * @createDate 2017/12/10
     */
    @Override
    public PropertyUserInfoPO checkUserByUserName(Map<String, String> param) {
        if (param == null || param.isEmpty()) {
            return null;
        }
        PropertyUserInfoPO userInfoPO = iPropertyUserInfoDao.checkUserByUserName(param);
        if(userInfoPO!=null){
            String lockUserNameKey = String.format("%s%s", RedisConstant.PROPERTY_LOGIN_ERROR_REDIS_KEY, userInfoPO.getUserId());
            loginErrorRedisService.del(lockUserNameKey);
        }
        return userInfoPO;
    }

    /**
     * <desc>
     *      查询物业用户所属项目信息
     * <desc/>
     * @param  userId   待查询用户userId
     * @return 查询到的项目状态信息
     * @author Biao.R
     * @createDate 2017/12/11
     */
    @Override
    public List<Integer> getProjectByUserId(String userId) {
        if (StringUtils.isEmpty(userId)) {
            return null;
        }
        return iPropertyUserInfoDao.getProjectByUserId(userId);
    }

    /**
     * <desc>
     *      物业登录错误处理
     * <desc/>
     * @param   propertyUserLoginDTO    登录用户DTO
     * @return  标准化响应结果
     * @author Biao.R
     * @createDate 2017/12/15
     */
    @Override
    public MessageVO loginErrorHandler(PropertyUserLoginDTO propertyUserLoginDTO) {
        String account = propertyUserLoginDTO.getAccount();
        String userId ="";
        //如果不是以项目编号登录，检查这个账号是否存在
        if (!account.matches(PlatformConstants.PROJECTID_REGEX)) {
            Map<String, Object> params = new HashMap<>();
            params.put("userName", account);
            List<PropertyUserInfoPO> userPOs = iPropertyUserInfoDao.getByFields(params);
            if (userPOs == null || userPOs.isEmpty()) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_ACCOUNT_IS_NOT_EXIST.getErrorCode());
            }
            userId = userPOs.get(0).getUserId();
        }else{
            //项目编号登录，需要找到该项目的物业管理员账号
            Map<String, Object> params = new HashMap<>();
            params.put("projectId", account.trim());
            PropertyUserInfoPO userInfoPO = this.checkUserByProjectId(params);
            if (userInfoPO != null) {
                account = userInfoPO.getUserName();
                userId = userInfoPO.getUserId();
            }else{
                return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_ACCOUNT_IS_NOT_EXIST.getErrorCode());
            }
        }

        //最大输入次数
        Integer limitErrorCount = PlatformConstants.PROPERTY_LOGIN_MAX_ERROR_COUNT;
        Map<String, Object> result = new HashMap<>();
        String errorCacheKey = String.format("%s%s", RedisConstant.PROPERTY_LOGIN_ERROR_REDIS_KEY, userId);
        PropertyLoginErrorCacheVO errorCacheVO = loginErrorRedisService.getObject(errorCacheKey, PropertyLoginErrorCacheVO.class);
        if (errorCacheVO == null) {

            //如果该账号之前没有输入错误，添加登陆错误缓存信息，记录输错次数
            errorCacheVO = new PropertyLoginErrorCacheVO(account,userId, 1);
            loginErrorRedisService.set(errorCacheKey, RedisConstant.PROPERTY_LOGIN_ERROR_TIME, errorCacheVO);
            result.put("errorCount", limitErrorCount - 1);
            return new MessageVO(PropertyErrorCodeEnum.PUB_ACCOUNT_PASSWORD_ERR.getErrorCode(), result);
        } else {

            //查询已经错误的次数：如果次数大于5，锁定30分钟
            Integer errorCount = errorCacheVO.getErrorCount();
            if (errorCount + 1 >= limitErrorCount) {

                //生成账号锁定缓存信息
                String lockUserNameKey = String.format("%s%s", RedisConstant.PROPERTY_LOGIN_ERROR_REDIS_KEY, userId);
                errorCacheVO = new PropertyLoginErrorCacheVO(account,userId, errorCount);
                errorCacheVO.setLockTime(new SimpleDateFormat(dateFormatStr).format(new Date()));
                loginErrorRedisService.set(lockUserNameKey, RedisConstant.PROPERTY_LOGIN_ERROR_TIME, errorCacheVO);
                result.put("remainTime", PlatformConstants.PROPERTY_LOGIN_ERROR_LOCK_TIME / 60);
                return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_ERROR_ACCOUNT_LOCKED.getErrorCode(), result);
            } else {

                //输错次数小于5次，更新缓存信息，并给出相应提示
                errorCacheVO = new PropertyLoginErrorCacheVO(account,userId, errorCount + 1);
                loginErrorRedisService.set(errorCacheKey, RedisConstant.PROPERTY_LOGIN_ERROR_TIME, errorCacheVO);
                result.put("errorCount", limitErrorCount - errorCount - 1);
                return new MessageVO(PropertyErrorCodeEnum.PUB_ACCOUNT_PASSWORD_ERR.getErrorCode(), result);
            }
        }
    }

    /**
     * <desc>
     *      检查账号是否被锁定
     * <desc/>
     * @param  account  检查的账号
     * @return  标准化响应结果
     * @author Biao.R
     * @createDate 2017/12/15
     */
    @Override
    public MessageVO getAccountLockDetail(String account) {
        try {
            //对于采用项目编号登录的，需要查询他的物业管理员账号,实际上锁定的是物业管理员的账号
            PropertyUserInfoPO userInfoPO = null;
                Map<String, Object> params = new HashMap<>();
            if (account.matches(PlatformConstants.PROJECTID_REGEX)) {
                params.put("projectId", account.trim());
                 userInfoPO = this.checkUserByProjectId(params);
                if (userInfoPO == null) {
                    return null;
                }
            }else{
            params.put("userName", account);
            List<PropertyUserInfoPO> userPOs = iPropertyUserInfoDao.getByFields(params);
            if (userPOs ==null || userPOs.isEmpty()) {
                return null;
            }
                userInfoPO=userPOs.get(0);
            }
            String lockUserNameKey = String.format("%s%s", RedisConstant.PROPERTY_LOGIN_ERROR_REDIS_KEY, userInfoPO.getUserId());
            PropertyLoginErrorCacheVO errorCacheVO = loginErrorRedisService.getObject(lockUserNameKey, PropertyLoginErrorCacheVO.class);
            Map<String,Object> result = new HashMap<>();
            if (errorCacheVO != null) {

                //计算当前时间和锁定时间，如果小于规定的锁定时间，返回相应提示信息
                String lockTimeStr = errorCacheVO.getLockTime();
                if (StringUtils.isNotEmpty(lockTimeStr)) {
                    Date lockTime = new SimpleDateFormat(dateFormatStr).parse(lockTimeStr);
                    long distanceTime = (new Date().getTime() - lockTime.getTime()) / 1000;
                    Long lockLimitTime = PlatformConstants.PROPERTY_LOGIN_ERROR_LOCK_TIME;
                    if (distanceTime < lockLimitTime) {
                        //在锁定时间内：返回锁定时间信息
                        result.put("remainTime",((lockLimitTime - distanceTime) / 60) + 1);
                        return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_ERROR_ACCOUNT_LOCKED.getErrorCode(), result);
                    } else {
                        //锁定时间已过，清空该账号的错误缓存数据
                        loginErrorRedisService.del(lockUserNameKey);
                    }
                }
            }
            return null;
        } catch (ParseException e) {
            throw new DataAccessException("【物业_getAccountLockDetail】检查账号是否被锁定异常", e);
        }
    }

    /**
     * <desc>
     *      根据电梯cardId查询userId
     * </desc>
     *
     * @param cardId
     * @return
     * @author Jiaqi.X
     * @createDate 2018/03/25
     */
    @Override
    public String getUserIdByCardId(String cardId){
        return iPropertyUserInfoDao.getUserIdByCardId(cardId);
    }

    /**
     * <desc>
     *     登录成功后根据userid查询当前用户下的小区信息
     * <desc/>
     *@param loginUserId
     * @return  MessageVO 标准格式化响应结果
     * @author JuGuang.S
     * @createDate 2018/07/04
     */
    @Override
    public List<PropertyProjectRoleVO> getUserProjectInfo(String loginUserId){
        String userId = loginUserId;
        return iPropertyUserInfoDao.getProjectRoleByUserId(userId,null);
    }

    /**
     * <desc>
     *      由项目id查询物业名称
     * </desc>
     *
     * @param projectId 项目id
     * @return 物业名称
     * @author wangzhi
     * @createDate 2018/08/31
     */
    @Override
    public String getPropertyNameByProjectId(String projectId) throws Exception {
        String propertyName =  iPropertyUserInfoDao.getPropertyNameByProjectIdAndRole5(projectId);
        if (StringUtils.isBlank(propertyName)) {
            propertyName = iPropertyUserInfoDao.getPropertyNameByProjectIdAndRole3(projectId);
        }
        return propertyName;
    }

    /**
     * <desc>
     *      由身份证序列号查询用户信息
     * </desc>
     *
     * @param idCardKey 身份证序列号
     * @return 用户信息
     * @author wangzhi
     * @createDate 2019/02/28
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Map<String, Object> getUserInfoByIdCardKey(String idCardKey,String projectId) throws Exception {
        return iPropertyUserInfoDao.getUserInfoByIdCardKey(idCardKey,projectId);
    }

    /**
     * <desc>
     *      找回密码时，通过账号获取绑定手机号
     * <desc/>
     *
     * @return 相关参数
     * @author wangzhi
     * @createDate 2019/12/25
     */
    @Override
    public Map<String, Object> getPhoneNumByUserName(String userName) throws Exception {
        Map<String, Object> params = new HashMap<>();
        params.put("userName", userName);
        List<PropertyUserInfoPO> propertyUserInfoPOS = iPropertyUserInfoDao.getByFields(params);
        if (propertyUserInfoPOS == null || propertyUserInfoPOS.isEmpty()) {
            params.remove("userName");
            params.put("result", -1);
            return params;
        }
        return iPropertyUserInfoDao.getPhoneNumByUserName(userName);
    }

    /**
     * <desc>
     *      根据用户id查询一个用户
     * <desc/>
     * @param  userId    用户id
     * @return  PropertyUserInfoPO
     * @author zhouchun
     * @createDate 2021-05-31
     */
    public PropertyUserInfoPO getByUserId(String userId) {
        return iPropertyUserInfoDao.getUserByUserId(userId);
    }

}